package chen.bupt.akka.demo

import akka.actor._
import akka.pattern.{ask, pipe}
import akka.util.Timeout
import scala.concurrent.duration._
import scala.concurrent.ExecutionContext.Implicits.global

/**
 * Created with IntelliJ IDEA.
 * User: chenlingpeng
 * Date: 2014/10/8
 * Time: 11:27
 *
 *
 */


object AkkaTest {

  case object Tick

  case object Shutdown

  case object Buy_?

  val a_+++++------ = 1

  val `ddddddfsd+++---` = 1

  val system = ActorSystem("clp")

  class MainActor extends Actor with ActorLogging {
    //    context.setReceiveTimeout(2 seconds)
    implicit val timeout2 = Timeout(5 second)

    override def receive: Receive = {
      case Shutdown =>
        log.info("will shut down")
        context become shuttingDown
      case a: Int =>
        log.info("main actor receive " + a + ", will deliver")
        val child = context.actorOf(Props[ChildActor](new ChildActor(a)), a.toString)
        context watch child
        child ! a
      case b: String =>
        log.info("receive from " + sender().path.name + " with path " + sender().path)
      //      case ReceiveTimeout =>
      //        log.info("timeout " + sender.path.name) // deadLetter
      case c: Double =>
        val child = context.actorOf(Props[ChildActor](new ChildActor(100)), 100.toString)
        context watch child
        log.info("receive double")
        //        val f = ask(child, 100)
        val f = child ? 100
        f.onComplete(_ => log.info("i'm complete"))
      case Tick =>
        val child = context.actorOf(Props[ChildActor](new ChildActor(101)), 101.toString)
        context watch child
        child ! "haha"
        log.info("tick")
      case Terminated(actor) =>
        log.info(actor.path.name + " is over")
    }


    private def shuttingDown: Receive = {
      case Terminated(actor) =>
        //        context.unwatch(actor)
        //        context.actorSelection("./*").
        log.info("actor " + actor.path.name + " is terminated")
        if (context.children.isEmpty) {
          log.info("stop!!!!")
          context.stop(self)
        } else {
          log.info("remain " + context.children.mkString(",,,") + " children")
        }
      case _ =>
        log.info("service unavailable now")
    }
  }

  class ChildActor(index: Int) extends Actor with ActorLogging {
        context.setReceiveTimeout(2 seconds)
    override val supervisorStrategy = OneForOneStrategy(){
      case _ => SupervisorStrategy.Restart
    }
    override def receive: Receive = {
      case a: Int =>
        log.info("child actor " + index + " receive " + a)
//        if (a == 1)
//          Thread.sleep(2000)
        sender ! a.toString
        //        throw new NullPointerException("nullp")
        context.stop(self)
      //      case ReceiveTimeout =>
      //        log.info("timeout " + sender.path.name)
    }


  }

  def main(args: Array[String]) {
    val mainactor = system.actorOf(Props[MainActor](new MainActor), "main-actor")
    (1 to 9).map(a =>
      mainactor ! a
    )
    (0 to 1).map {
      a =>
        mainactor ! a
    }
    mainactor ! 3.4
    mainactor ! Tick
    mainactor ! Shutdown
    Thread.sleep(5000)
    system.shutdown()
  }

}
